<html>
    <head>
        <title>Bokeh Example</title>
        <meta charset="iso-8859-1" />
        <link rel="icon" type="image/x-icon" href="./favicon.png" />
        <script
            type="text/javascript"
            src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"
        ></script>
        <script
            type="text/javascript"
            src="https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js"
        ></script>
        <script
            type="text/javascript"
            src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"
        ></script>
        <script
            type="text/javascript"
            src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"
        ></script>
        <script
            type="text/javascript"
            src="https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js"
        ></script>
        <link rel="stylesheet" href="./assets/css/examples.css" />

        <script type="text/javascript">
            Bokeh.set_log_level("info");
        </script>
        <link
            rel="stylesheet"
            href="https://pyscript.net/latest/pyscript.css"
        />

        <script defer src="https://pyscript.net/latest/pyscript.js"></script>
    </head>
    <body>
        <nav class="navbar" style="background-color: #000000">
            <div class="app-header">
                <a href="/">
                    <img src="./logo.png" class="logo" />
                </a>
                <a class="title" href="" style="color: #f0ab3c"
                    >Bokeh Example</a
                >
            </div>
        </nav>
        <py-tutor>
            <section class="pyscript">
                <h1>Bokeh Example</h1>
                <div id="myplot"></div>

                <py-config>
                    packages = [
                      "https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl",
                      "numpy",
                    ]
                    plugins = [
                      "https://pyscript.net/latest/plugins/python/py_tutor.py"
                    ]
                </py-config>

                <py-script id="main">
                    import asyncio
                    import json
                    import pyodide

                    from js import Bokeh, console, JSON

                    from bokeh import __version__
                    from bokeh.document import Document
                    from bokeh.embed.util import OutputDocumentFor, standalone_docs_json_and_render_items
                    from bokeh.models import Slider, Div
                    from bokeh.layouts import Row
                    from bokeh.protocol.messages.patch_doc import process_document_events

                    # create a new plot with default tools, using figure
                    p = Slider(start=0.1, end=10, value=1, step=.1, title="Amplitude")
                    div = Div(text=f'Amplitude is: {p.value}')

                    def callback(attr, old, new):
                        div.text = f'Amplitude is: {new}'

                    p.on_change('value', callback)

                    row = Row(children=[p, div])

                    def doc_json(model, target):
                        with OutputDocumentFor([model]) as doc:
                            doc.title = ""
                            docs_json, _ = standalone_docs_json_and_render_items(
                                [model], suppress_callback_warning=True
                            )

                        doc_json = list(docs_json.values())[0]
                        root_id = doc_json['roots']['root_ids'][0]

                        return doc, json.dumps(dict(
                            target_id = target,
                            root_id   = root_id,
                            doc       = doc_json,
                            version   = __version__,
                        ))

                    def _link_docs(pydoc, jsdoc):
                        def jssync(event):
                            if getattr(event, 'setter_id', None) is not None:
                                return
                            events = [event]
                            json_patch = jsdoc.create_json_patch_string(pyodide.ffi.to_js(events))
                            pydoc.apply_json_patch(json.loads(json_patch))

                        jsdoc.on_change(pyodide.ffi.create_proxy(jssync), pyodide.ffi.to_js(False))

                        def pysync(event):
                            json_patch, buffers = process_document_events([event], use_buffers=True)
                            buffer_map = {}
                            for (ref, buffer) in buffers:
                                buffer_map[ref['id']] = buffer
                            jsdoc.apply_json_patch(JSON.parse(json_patch), pyodide.ffi.to_js(buffer_map), setter_id='js')

                        pydoc.on_change(pysync)

                    async def show(plot, target):
                        pydoc, model_json = doc_json(plot, target)
                        views = await Bokeh.embed.embed_item(JSON.parse(model_json))
                        jsdoc = views[0].model.document
                        _link_docs(pydoc, jsdoc)

                    asyncio.ensure_future(show(row, 'myplot'))
                </py-script>
            </section>
        </py-tutor>
    </body>
</html>
